import requests
import pandas as pd
from datetime import datetime, timedelta, date
import logging
from typing import Dict, List, Optional
import xml.etree.ElementTree as ET

logger = logging.getLogger(__name__)

class ENTSOEAPIService:
    """ENTSO-E API服务"""
    
    def __init__(self, token: str = "6dfc84cd-d400-493d-a71f-6ea587c3d53b"):
        self.token = token
        self.base_url = "https://transparency.entsoe.eu/api"
        
        # 比利时区域代码
        self.area_codes = {
            "BE": "10YBE----------2",  # 比利时
        }
    
    def get_load_data(self, start_date: str, end_date: str, area: str = "BE") -> Optional[pd.DataFrame]:
        """
        获取负荷数据
        
        Args:
            start_date: 开始日期 (YYYY-MM-DD)
            end_date: 结束日期 (YYYY-MM-DD)
            area: 区域代码 (默认比利时)
        
        Returns:
            DataFrame包含负荷数据，列：datetime, load_value
        """
        try:
            area_code = self.area_codes.get(area, area)
            
            # 构建API请求URL
            url = f"{self.base_url}"
            params = {
                'securityToken': self.token,
                'documentType': 'A65',  # 实际负荷
                'processType': 'A16',   # 实际值
                'outBiddingZone_Domain': area_code,
                'periodStart': f"{start_date}0000",
                'periodEnd': f"{end_date}2359"
            }
            
            logger.info(f"请求ENTSO-E API: {start_date} 到 {end_date}")
            response = requests.get(url, params=params, timeout=30)
            
            if response.status_code != 200:
                logger.error(f"API请求失败: {response.status_code} - {response.text}")
                return None
            
            # 解析XML响应
            root = ET.fromstring(response.content)
            
            # 提取时间序列数据
            load_data = []
            
            # 查找所有时间序列
            for series in root.findall('.//Series'):
                # 获取时间点
                for point in series.findall('.//Point'):
                    position_elem = point.find('position')
                    quantity_elem = point.find('quantity')
                    
                    if position_elem is None or quantity_elem is None:
                        continue
                        
                    position = int(position_elem.text or '0')
                    quantity = float(quantity_elem.text or '0.0')
                    
                    # 计算实际时间
                    # 假设position=1对应00:00，position=2对应00:15，以此类推
                    hours = (position - 1) // 4
                    minutes = ((position - 1) % 4) * 15
                    
                    # 从开始日期计算实际日期
                    start_dt = datetime.strptime(start_date, '%Y-%m-%d')
                    actual_dt = start_dt + timedelta(hours=hours, minutes=minutes)
                    
                    load_data.append({
                        'datetime': actual_dt,
                        'load_value': quantity
                    })
            
            if not load_data:
                logger.warning("未找到负荷数据")
                return None
            
            # 转换为DataFrame
            df = pd.DataFrame(load_data)
            df = df.sort_values('datetime').reset_index(drop=True)
            
            logger.info(f"成功获取 {len(df)} 条负荷数据")
            return df
            
        except Exception as e:
            logger.error(f"获取负荷数据失败: {e}")
            return None
    

    
    def validate_token(self) -> bool:
        """验证API token是否有效"""
        try:
            # 尝试获取昨天的数据来验证token
            yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
            
            url = f"{self.base_url}"
            params = {
                'securityToken': self.token,
                'documentType': 'A65',
                'processType': 'A16',
                'outBiddingZone_Domain': self.area_codes['BE'],
                'periodStart': f"{yesterday}0000",
                'periodEnd': f"{yesterday}2359"
            }
            
            response = requests.get(url, params=params, timeout=10)
            
            if response.status_code == 200:
                logger.info("ENTSO-E API token验证成功")
                return True
            else:
                logger.error(f"ENTSO-E API token验证失败: {response.status_code}")
                return False
                
        except Exception as e:
            logger.error(f"验证token时发生错误: {e}")
            return False 